package main

import (
	"bufio"
	"fmt"
	"io"
	"learn-go/7.functional/fib"
	"strings"
)

// 1, 1, 2, 3, 5, 8, 13, ...
//    a, b
//       a, b
//func fibonacci() func() int {
//	a, b := 0, 1
//	return func() int {
//		a, b = b, a+b
//		return a
//	}
//}

// 为函数实现接口
//type intGen func() int

//func (g intGen) Read(p []byte) (n int, err error) {
//	next := g()
//	if next > 10000 { // 斐波那契数列永远读不完
//		return 0, io.EOF
//	}
//	s := fmt.Sprintf("%d\n", next)
//	// todo: incorrect if p is too small!
//	return strings.NewReader(s).Read(p)
//}

// #4 把中间结果缓存起来，这里就要把initGen做成一个struct才行
type intGen struct {
	gen           func() int
	currentReader io.Reader
}

func (g *intGen) Read(p []byte) (n int, err error) {
	err = io.EOF
	if g.currentReader != nil {
		n, err = g.currentReader.Read(p)
	}
	if err == io.EOF {
		next := g.gen()
		s := fmt.Sprintf("%d\n", next)
		g.currentReader = strings.NewReader(s)
		if n == 0 {
			n, err = g.currentReader.Read(p)
		}
	}
	return n, err
}

func printFileContents(reader io.Reader) {
	scanner := bufio.NewScanner(reader)

	for scanner.Scan() {
		fmt.Println(scanner.Text())
	}
}

func main() {
	//f := fibonacci()

	// #1
	//fmt.Println(f()) // 1
	//fmt.Println(f()) // 1
	//fmt.Println(f()) // 2
	//fmt.Println(f()) // 3
	//fmt.Println(f()) // 5
	//fmt.Println(f()) // 8
	//fmt.Println(f()) // 13
	//fmt.Println(f()) // 21

	// #2
	//printFileContents(f)
	//printFileContents(f)
	//printFileContents(f)
	//printFileContents(f)
	//printFileContents(f)

	// #3 p只能读1个数字
	//for i := 0; i < 20; i++ {
	//	b := make([]byte, 1)
	//	n, err := f.Read(b)
	//	fmt.Printf("%d bytes read: %q, err = %v\n", n, b, err)
	//}

	// #4
	f := &intGen{
		gen:           fib.Fibonacci(),
		currentReader: nil,
	}
	for i := 0; i < 20; i++ {
		b := make([]byte, 1)
		n, err := f.Read(b)
		fmt.Printf("%d bytes read: %q, err = %v\n", n, b, err)
	}
}
